package com.cloud.plugin

import org.gradle.api.Action
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.XmlProvider
import org.gradle.api.artifacts.ModuleDependency
import org.gradle.api.artifacts.dsl.ArtifactHandler
import org.gradle.api.component.SoftwareComponent
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenArtifact
import org.gradle.api.publish.maven.MavenPom
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin
import org.gradle.api.tasks.TaskDependency

import javax.annotation.Nullable

/**
 * 描述：
 *
 * @author FineEx   2021/12/3
 * @version 1.0
 */
public class PublishMaven implements Plugin<Project> {
    def publishConfig = "publishConfig"

    @Override
    void apply(Project project) {
        def publishingConfig = project.extensions.create(publishConfig, PublishConfig)

        project.plugins.apply MavenPublishPlugin
        PublishingExtension publishing = project.extensions.getByType(PublishingExtension)

        project.afterEvaluate {
            for (SoftwareComponent components : project.components) {
                publishing.publications({ publications ->
                    publications.create(components.name, MavenPublication.class, { MavenPublication publication ->
                        publication.groupId = publishingConfig.groupId
                        publication.artifactId = publishingConfig.artifactId
                        publication.version = publishingConfig.version
                        if (publishingConfig.jarTask != null) {
                            publication.artifact(publishingConfig.jarTask)
                        }
                        publication.from(components)
                        publication.pom {
                            mavenPom ->
                                {
                                    configPom(mavenPom, publishingConfig)
                                    mavenPom.withXml(new Action<XmlProvider>() {
                                        @Override
                                        void execute(XmlProvider xmlProvider) {
                                            Node node = xmlProvider.asNode()
                                            def dependenciesNode = node.get('dependencies')
                                            def dependenciesAdded = []
                                            if (dependenciesNode == null || dependenciesNode.isEmpty()) {
                                                dependenciesNode = node.appendNode('dependencies')
                                                project.configurations.each { conf ->
                                                    conf.allDependencies.each { dependency ->
                                                        dependency.artifacts.each { art ->
                                                            def dependencyName = "$dependency.group:$dependency.name:$dependency.version${(art.classifier != null) ? ":$art.classifier" : ""}"
                                                            if (!dependenciesAdded.contains(dependencyName)) {
                                                                dependenciesAdded.add(dependencyName)
                                                                def dependencyNode = dependenciesNode.appendNode('dependency')
                                                                dependencyNode.appendNode('groupId', dependency.group)
                                                                dependencyNode.appendNode('artifactId', dependency.name)
                                                                dependencyNode.appendNode('version', dependency.version)
                                                                if (art.extension != null) {
                                                                    dependencyNode.appendNode('type', art.extension)
                                                                }
                                                                if (art.classifier != null) {
                                                                    dependencyNode.appendNode('classifier', art.classifier)
                                                                }

                                                                if (dependency instanceof ModuleDependency
                                                                        && !dependency.getExcludeRules().isEmpty()) {
                                                                    def exclusionsNode = dependencyNode.appendNode('exclusions')
                                                                    dependency.getExcludeRules().each { rule ->
                                                                        def exclusionNode = exclusionsNode.appendNode('exclusion')
                                                                        if (rule.getGroup() != null) {
                                                                            exclusionNode.appendNode('groupId', rule.getGroup())
                                                                        }
                                                                        if (rule.getModule() != null) {
                                                                            exclusionNode.appendNode('artifactId', rule.getModule())
                                                                        }
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    })
                                }
                        }
                    })
                })
            }

            publishing.repositories { artifactRepositories ->
                artifactRepositories.maven { mavenArtifactRepository ->
                    mavenArtifactRepository.allowInsecureProtocol = true
                    mavenArtifactRepository.url = publishingConfig.snapshot ? publishingConfig.repoSnapshot : publishingConfig.repoRelease
                    mavenArtifactRepository.credentials {
                        credentials ->
                            credentials.username = publishingConfig.repoName
                            credentials.password = publishingConfig.repoPassword
                    }
                }
            }
        }
    }

    static void configPom(MavenPom mavenPom, PublishConfig config) {
        mavenPom.name = config.pomName
        mavenPom.description = config.pomDescription
        mavenPom.url = config.pomUrl
    }
}
